﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Xml;
using System.Reflection;
using System.IO;
using Parallel3M.parallel3m.framework;

namespace Parallel3M.parallel3m.protocol
{
    public class ProtocolProtype
    {
        public string name;
        public string description;
        public string assemblyPath;
        public ProtocolParallelApplication app;
        public Hashtable protocolHandlers = new Hashtable();
        public ProtocolServiceAbstract protocolService;
        public string status = "noconnect";

        public ProtocolPayload Send_Protocol_Command_Request(string command, Hashtable parameters, int routeCount)
        {
            ProtocolPayload payload = new ProtocolPayload();
            payload.id = Guid.NewGuid().ToString();
            payload.domain = name;
            payload.handlerid = command;
            payload.type = PAYLOADCONSTRANT.TYPE_REQUEST;
            payload.routeCount = routeCount;
            payload.request = "<request>";
            foreach (DictionaryEntry paraEntry in parameters)
            {
                payload.request += "<" + paraEntry.Key + ">" + paraEntry.Value + "</" + paraEntry.Key + ">";
            }
            payload.request += "</request>";
            return payload;
        }

        public ProtocolPayload Send_Protocol_Command_Response(string command, Hashtable parameters, int routeCount)
        {
            ProtocolPayload payload = new ProtocolPayload();
            payload.id = Guid.NewGuid().ToString();
            payload.domain = name;
            payload.handlerid = command;
            payload.type = PAYLOADCONSTRANT.TYPE_RESPONSE;
            payload.routeCount = routeCount;
            payload.response = "<response>";
            foreach (DictionaryEntry paraEntry in parameters)
            {
                payload.response += "<" + paraEntry.Key + ">" + paraEntry.Value + "</" + paraEntry.Key + ">";
            }
            payload.response += "</response>";
            return payload;
        }

        public void loadProtocolfile(string protocolfile)
        {
            XmlDocument doc = new XmlDocument();
            doc.Load(protocolfile);
            XmlNodeList nodes = doc.ChildNodes;

            XmlNode protocolNode = nodes[0];
            XmlAttributeCollection atts = protocolNode.Attributes;

            Assembly protocl_assembly = null;
            Assembly service_assembly = null;

            String serviceName="";

            foreach (XmlAttribute att in atts)
            {
                if (att.Name == "name")
                {
                    name = att.Value;
                }
                else if (att.Name == "description")
                {
                    description = att.Value;
                }
                else if (att.Name == "path")
                {
                    assemblyPath = att.Value;
                    
                }
                else if (att.Name == "service")
                {                    
                    serviceName = att.Value;

                    int pos = serviceName.IndexOf('.');
                    string service_dll_name=serviceName.Substring(0,pos);

                    Assembly[] assems = AppDomain.CurrentDomain.GetAssemblies();
                    foreach (Assembly assem in assems)
                    {
                        string assembly_name = assem.GetName().Name;
                        if (assembly_name == service_dll_name)
                        {
                            service_assembly = assem;
                            break;
                        }
                    }
                   
                    if(service_assembly == null)
                    {
                        string path = Directory.GetCurrentDirectory();
                        service_assembly=Assembly.LoadFile(path + "/" + service_dll_name + ".dll");
                    }
                    protocolService = (ProtocolServiceAbstract)Activator.CreateInstance(service_assembly.GetType(serviceName));
                    protocolService.proctol = this;
                    protocolService.init();
                }
            }

            //inistal protocol service
            //get the instance by the handler_name with the path
            

            //
            XmlNodeList protocolCommandNodes = protocolNode.SelectNodes("/protocol/protocolitem[@handlerid!='']");

            foreach (XmlNode node in protocolCommandNodes)
            {
                String COMMAND_NAME = "";
                string handler_name = "";
                XmlAttributeCollection command_atts = node.Attributes;

                foreach (XmlAttribute att in command_atts)
                {

                    if (att.Name == "name")
                    {
                        COMMAND_NAME = att.Value;
                    }
                    
                    if (att.Name == "handlerid")
                    {
                            
                            handler_name = att.Value;
                        
                           //load the protocl_assembly
                            if (protocl_assembly == null)
                            {
                                    int pos = handler_name.IndexOf('.');
                                    string protocol_dll_name = handler_name.Substring(0, pos);

                                    Assembly[] assems = AppDomain.CurrentDomain.GetAssemblies();
                                    foreach (Assembly assem in assems)
                                    {
                                        string assembly_name = assem.GetName().Name;
                                        if (assembly_name == protocol_dll_name)
                                        {
                                            protocl_assembly = assem;
                                            break;
                                        }
                                    }

                                    if (protocl_assembly == null)
                                    {
                                        string path = Directory.GetCurrentDirectory();
                                        protocl_assembly = Assembly.LoadFile(path + "/" + protocol_dll_name + ".dll");
                                    }
                            }
                       
                        }

                            
                
                     }

                if (handler_name != null && handler_name != "")
                {
                    //get the instance
                    ProtocolHandler handlerInstance = (ProtocolHandler)Activator.CreateInstance(protocl_assembly.GetType(handler_name));

                    //                       
                    if (handlerInstance != null)
                    {
                        handlerInstance.protocol = this;
                        protocolHandlers.Add(COMMAND_NAME, handlerInstance);
                    }
                }


                /*
                foreach (XmlNode childnode in node)
                {
                    if (childnode.Name == "request")
                    {
                        XmlAttributeCollection command_request_atts = childnode.Attributes;
                        foreach (XmlAttribute att in command_request_atts)
                        {
                            if (att.Name == "handlerid")
                            {
                                ProtocolHandler handlerInstance;
                                string handler_name = att.Value;
                                //get the instance by the handler_name with the path
                                if (assembly == null)
                                {
                                    handlerInstance = (ProtocolHandler)Activator.CreateInstance(null, handler_name).Unwrap();
                                }
                                else
                                {
                                    handlerInstance = (ProtocolHandler)Activator.CreateInstance(assembly.GetType(handler_name));  
                                }
                                //
                                COMMAND_NAME += "_REQUEST";
                                if (handlerInstance != null)
                                {
                                    handlerInstance.protocol = this;
                                    protocolHandlers.Add(COMMAND_NAME, handlerInstance);
                                }

                            }
                            
                        }
                    }
                    else if (childnode.Name == "response")
                    {
                        XmlAttributeCollection command_response_atts = childnode.Attributes;
                        foreach (XmlAttribute att in command_response_atts)
                        {
                            if (att.Name == "handlerid")
                            {
                                ProtocolHandler handlerInstance;
                                string handler_name = att.Value;
                                //get the instance by the handler_name with the path
                                if (assembly == null)
                                {
                                    handlerInstance = (ProtocolHandler)Activator.CreateInstance(null, handler_name).Unwrap();
                                }
                                else
                                {
                                    handlerInstance = (ProtocolHandler)Activator.CreateInstance(assembly.GetType(handler_name));
                                }
                                //
                                COMMAND_NAME += "_RESPONSE";
                                if (handlerInstance != null)
                                {
                                    handlerInstance.protocol = this;
                                    protocolHandlers.Add(COMMAND_NAME, handlerInstance);
                                }

                            }

                        }

                    }

                }*/
            }

        }

    }
}
